// 示例 1：

// 输入：s = "ADOBECODEBANC", t = "ABC"
// 输出："BANC"
// 解释：最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
// 示例 2：

// 输入：s = "a", t = "a"
// 输出："a"
// 解释：整个字符串 s 是最小覆盖子串。
// 示例 3:

// 输入: s = "a", t = "aa"
// 输出: ""
// 解释: t 中两个字符 'a' 均应包含在 s 的子串中，
// 因此没有符合条件的子字符串，返回空字符串。

s = "ADOBECODEBANC", t = "ABC"

var minWindow = function (s, t) {
    let hashT = {} // t 地哈希表
    for (let str of t) {
        hashT[str] = hashT[str] || 0
        hashT[str]++
    }

    let window = {} // 当前窗口
    let left = 0, right = 0 // 双指针
    let start = 0, maxLen = Infinity
    let count = 0 // 当前窗口t中字母出现次数
    let size = Object.keys(hashT).length // t中字母出现次数

    while (right < s.length) {
        let char = s[right]
        right++
        if (hashT[char]) { // 当前s中字母在t中存在
            window[char] = (window[char] || 0) + 1 // 记录到窗口中
            if (hashT[char] === window[char]) { // 如果窗口中字母出现次数等于t哈希表出现次数
                count++ // 说明已找到一种字母
            }
        }

        while (count === size) { // t中字母在窗口中全部出现
            if (right - left < maxLen) { // 收集最小长度
                start = left
                maxLen = right - left
            }
            let str = s[left]
            left++

            if (hashT[str]) { // 当左指针移动到t中字母时
                if (hashT[str] === window[str]) {
                    count--
                }
                window[str]--
            }
        }
    }
    return maxLen === Infinity ? "" : s.slice(start, start + maxLen)
};

console.log(minWindow(s, t));
